package com.lovo.shirodemo.config;

import com.lovo.shirodemo.model.FunctionInfoDO;
import com.lovo.shirodemo.service.FunctionInfoService;
import com.lovo.shirodemo.shiro.CustomRealm;
import com.lovo.shirodemo.shiro.RestAuthorizationFilter;
import com.lovo.shirodemo.shiro.RestShiroFilterFactoryBean;
import com.lovo.shirodemo.shiro.ShiroFormAuthenticationFilter;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
public class ShiroConfig {
    /**
     * 配置Shiro核心 安全管理器 SecurityManager
     * SecurityManager安全管理器：所有与安全有关的操作都会与SecurityManager交互；
     * 且它管理着所有Subject；负责与后边介绍的其他组件进行交互。（类似于SpringMVC中的DispatcherServlet控制器）
     */
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //将自定义的realm交给SecurityManager管理
        securityManager.setRealm(customRealm());
        return securityManager;
    }

    /**
     * 配置Shiro的Web过滤器，拦截浏览器请求并交给SecurityManager处理     * @return
     */
    @Bean
    public ShiroFilterFactoryBean webFilter(SecurityManager securityManager,FunctionInfoService functionInfoService) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new RestShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
        filters.put("perms", new RestAuthorizationFilter());
        filters.put("authc", new ShiroFormAuthenticationFilter());
        //配置拦截链 使用LinkedHashMap,因为LinkedHashMap是有序的，shiro会根据添加的顺序进行拦截
        // Map<K,V> K指的是拦截的url V值的是该url是否拦截
         Map<String,String> filterChainMap = functionInfoService.loadFilterChainDefinitionMap();
        // 组装过滤路径
//        for(FunctionInfoDO functionInfoDO : functionInfoList){
//            String url = functionInfoDO.getUrl();
//            if(functionInfoDO.getMethod() != null && !"".equals(functionInfoDO.getMethod())){
//                url += "==" + functionInfoDO.getMethod();
//            }
//            filterChainMap.put(url,"perms["+functionInfoDO.getFunctionName()+"]");
//        }

        // 设置拦截请求后跳转的URL.
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 设置权限不匹配时跳转的URL
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
        return shiroFilterFactoryBean;
    }
    @Bean
    public CustomRealm customRealm(){
        return new CustomRealm();
    }

    /**
     * 开启aop注解支持
     * 即在controller中使用 @RequiresPermissions("user/userList")
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor attributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        //设置安全管理器
        attributeSourceAdvisor.setSecurityManager(securityManager);
        return attributeSourceAdvisor;
    }

    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }

}
